
package com.zhongketech.sunflower.utils;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.util.Log;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import com.zhongketech.sunflower.MyApplication;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;

public class ImageUtil {
    private static final String TAG = "ImageUtilImpl";

    private static final int TIME_OUT = 8000;// ms

    private static final int BUFFER_SIZE = 4096;

    /**
     * 获取下载文件的InputStream对象
     * 
     * @param urlStr 下载文件的地址
     * @return 返回InputStream文件对象
     */
    public static InputStream GetInputStream(String urlStr)
            throws MalformedURLException, IOException {
        return GetInputStream(urlStr, "GET");
    }

    /**
     * 获取下载文件的InputStream对象
     * 
     * @param urlStr 下载文件的地址
     * @return 返回InputStream文件对象
     */
    public static InputStream GetInputStream(String urlStr, String method)
            throws MalformedURLException, IOException {
        URL url = new URL(urlStr);
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
        httpConn.setConnectTimeout(TIME_OUT);
        httpConn.setReadTimeout(TIME_OUT);
        httpConn.setRequestMethod(method);
        httpConn.setDoInput(true);
        InputStream inputStream = httpConn.getInputStream();
        return inputStream;
    }

    /**
     * 下载文本文件，直接返回字符串
     * 
     * @param urlStr 下载地址 flg 是否转化成国标GBK
     * @return 返回文本文件的字符串
     */
    public static String getData(String urlStr, boolean flg) {
        StringBuffer sBuffer = new StringBuffer();
        String line = null;
        BufferedReader bufferedReader = null;

        try {
            if (flg) {
                bufferedReader = new BufferedReader(new InputStreamReader(
                        GetInputStream(urlStr), "UTF-8"));
            } else {
                bufferedReader = new BufferedReader(new InputStreamReader(
                        GetInputStream(urlStr)));
            }

            while ((line = bufferedReader.readLine()) != null) {
                sBuffer.append(line);
            }
            ILog.d(TAG, "ImageUtilImpl download data OK : " + urlStr);
        } catch (Exception e) {
            // java.net.UnknownHostException: Unable to resolve host
            // "cibn-iuc.coship.com": No address associated with hostname
            ILog.e(TAG,
                    "ImageUtilImpl getData(" + urlStr + ")Exception: "
                            + e.getMessage());
        } finally {
            try {
                if (null != bufferedReader) {
                    bufferedReader.close();
                }
            } catch (Exception e) {
                ILog.e(TAG, e.getMessage());
            }
        }

        return sBuffer.toString();

    }

    public static String getAppData(String urlStr) {
        synchronized (ImageUtil.class) {
            HttpGet get = new HttpGet(urlStr);
            HttpClient client = new DefaultHttpClient();
            try {
                HttpResponse response = client.execute(get);
                if (response.getStatusLine().getStatusCode() == 200) {
                    HttpEntity entity = response.getEntity();
                    if (null != entity) {
                        String string = EntityUtils.toString(entity);
                        ILog.d(TAG, " string = " + string);
                        return string;
                    }
                } else {
                    ILog.d(TAG, " the request code : "
                            + response.getStatusLine().getStatusCode());
                }

            } catch (ClientProtocolException e) {
                ILog.e(TAG, e.getMessage());
            } catch (IOException e) {
                ILog.e(TAG, e.getMessage());
            }
        }
        return null;
    }

    /**
     * get image from server
     * 
     * @param file : the target file while to be written
     * @param filePath : the url which is to be download
     * @return true : download successful; false : download failed
     */
    public static boolean downloadAndSaveImage(final File imgFile,
            final String filePath) throws Exception {

        boolean isOk = false;

        if (null == imgFile) {
            return isOk;
        }

        if (null == filePath || filePath.equals("")) {
            return isOk;
        }
        final String imgFilePath = imgFile.getPath();
        final File tempImgFile = new File(imgFilePath + ".bak");
        if (tempImgFile.exists()) {
            tempImgFile.delete();
        }

        InputStream is = null;
        FileOutputStream fos = null;

        // 从网络上获取图片
        final URL url = new URL(filePath);
        final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(TIME_OUT);
        conn.setRequestMethod("GET");
        conn.setDoInput(true);
        final int count = conn.getResponseCode();

        if (count != HttpURLConnection.HTTP_OK) {
            ILog.e(TAG, " request img error, HTTP is not OK to : " + filePath);
            return isOk;
        }

        final long imgFileSize = conn.getContentLength();
        final byte[] buffer = new byte[BUFFER_SIZE];
        try {
            is = conn.getInputStream();
            fos = new FileOutputStream(tempImgFile);
            int len = 0;

            while ((len = is.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }

            final long filesize = tempImgFile.length();

            if (filesize != imgFileSize) {
                ILog.e(TAG, " Download img error, the url : " + filePath);
            }

            isOk = tempImgFile.renameTo(imgFile);
        } catch (Exception e) {
            ILog.e(TAG, "downloadAndSaveImage() ===>> " + e.getMessage());
            tempImgFile.delete();
            isOk = false;
        } finally {
            if (null != is) {
                is.close();
            }

            if (null != fos) {
                fos.flush();
                fos.close();
            }
        }

        return isOk;
    }

    public static byte[] downloadImageToBitmap(String imageUrl)
            throws Exception {
        if (null == imageUrl || imageUrl.equals("")) {
            return null;
        }

        // 从网络上获取图片
        URL url = new URL(imageUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(TIME_OUT);
        conn.setRequestMethod("GET");
        conn.setDoInput(true);

        if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {

            InputStream is = conn.getInputStream();
            final ByteArrayOutputStream os = new ByteArrayOutputStream();
            byte[] buffer = new byte[BUFFER_SIZE];
            int len = 0;

            while ((len = is.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }
            os.flush();
            byte[] bitmapByte = os.toByteArray();
            is.close();
            os.close();
            buffer = null;

            // Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapByte, 0,
            // bitmapByte.length);

            ILog.d(TAG, "AppPoster_Download-OK: " + imageUrl);
            return bitmapByte;
        }

        return null;
    }

    public static Bitmap downloadBitmap(String imgUrl) {
        Bitmap bitmap = null;
        URL url;
        InputStream inputStream = null;
        HttpURLConnection conn = null;
        try {
            url = new URL(imgUrl);
            conn = (HttpURLConnection) url.openConnection();
            conn.setDoInput(true);
            conn.connect();
            inputStream = conn.getInputStream();
            bitmap = BitmapFactory.decodeStream(inputStream);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return bitmap;
    }

    public static String encoder(String value)
            throws UnsupportedEncodingException {
        // 转中文
        String enUft = URLEncoder.encode(value, "UTF-8");

        // 逆转
        // java.net.URLDecoder urlDecoder = new java.net.URLDecoder();
        // String str = urlDecoder.decode(enUft, "UTF-8");

        return enUft;
    }

    /**
     * Decode and sample down a bitmap from resources to the requested width and
     * height.
     * 
     * @param res The resources object containing the image data
     * @param resId The resource id of the image data
     * @param reqWidth The requested width of the resulting bitmap
     * @param reqHeight The requested height of the resulting bitmap
     * @return A bitmap sampled down from the original with the same aspect
     *         ratio and dimensions that are equal to or greater than the
     *         requested width and height
     */
    public static Bitmap decodeSampledBitmapFromResource(Resources res,
            int resId, int reqWidth, int reqHeight) {

        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth,
                reqHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(res, resId, options);
    }

    /**
     * Decode and sample down a bitmap from a file to the requested width and
     * height.
     * 
     * @param filename The full path of the file to decode
     * @param reqWidth The requested width of the resulting bitmap
     * @param reqHeight The requested height of the resulting bitmap
     * @return A bitmap sampled down from the original with the same aspect
     *         ratio and dimensions that are equal to or greater than the
     *         requested width and height
     */
    public static Bitmap decodeSampledBitmapFromFile(String filename,
            int reqWidth, int reqHeight) {
        String key = filename + reqWidth + "x" + reqHeight;
        ImageCache cache = MyApplication.getInstance().mImageCache;
        Bitmap bt = cache.get(key);
        if (bt != null)
            return bt;
        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        // options.inJustDecodeBounds = true;
        // BitmapFactory.decodeFile(filename, options);

        // Calculate inSampleSize
        // options.inSampleSize = calculateInSampleSize(options, reqWidth,
        // reqHeight);

        // Decode bitmap with inSampleSize set
        // options.inJustDecodeBounds = false;
        options.inPreferredConfig = Config.ARGB_8888;
        bt = BitmapFactory.decodeFile(filename, options);
        if (bt != null) {
            cache.put(key, bt);
        }
        return bt;
    }

    /**
     * Decode and sample down a bitmap from a file input stream to the requested
     * width and height.
     * 
     * @param fileDescriptor The file descriptor to read from
     * @param reqWidth The requested width of the resulting bitmap
     * @param reqHeight The requested height of the resulting bitmap
     * @return A bitmap sampled down from the original with the same aspect
     *         ratio and dimensions that are equal to or greater than the
     *         requested width and height
     */
    public static Bitmap decodeSampledBitmapFromDescriptor(
            FileDescriptor fileDescriptor, int reqWidth, int reqHeight) {

        Bitmap bitmap = null;
        try {
            // First decode with inJustDecodeBounds=true to check dimensions
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);

            // Calculate inSampleSize
            options.inSampleSize = calculateInSampleSize(options, reqWidth,
                    reqHeight);

            // Decode bitmap with inSampleSize set
            options.inJustDecodeBounds = false;
            bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor, null,
                    options);

        } catch (OutOfMemoryError e) {
            ILog.e(TAG, "OutOfMemoryError ");
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    /**
     * Calculate an inSampleSize for use in a {@link BitmapFactory.Options}
     * object when decoding bitmaps using the decode* methods from
     * {@link BitmapFactory}. This implementation calculates the closest
     * inSampleSize that will result in the final decoded bitmap having a width
     * and height equal to or larger than the requested width and height. This
     * implementation does not ensure a power of 2 is returned for inSampleSize
     * which can be faster when decoding but results in a larger bitmap which
     * isn't as useful for caching purposes.
     * 
     * @param options An options object with out* params already populated (run
     *            through a decode* method with inJustDecodeBounds==true
     * @param reqWidth The requested width of the resulting bitmap
     * @param reqHeight The requested height of the resulting bitmap
     * @return The value to be used for inSampleSize
     */
    public static int calculateInSampleSize(BitmapFactory.Options options,
            int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            if (width > height) {
                inSampleSize = Math.round((float) height / (float) reqHeight);
            } else {
                inSampleSize = Math.round((float) width / (float) reqWidth);
            }

            // This offers some additional logic in case the image has a strange
            // aspect ratio. For example, a panorama may have a much larger
            // width than height. In these cases the total pixels might still
            // end up being too large to fit comfortably in memory, so we should
            // be more aggressive with sample down the image (=larger
            // inSampleSize).

            final float totalPixels = width * height;

            // Anything more than 2x the requested pixels we'll sample down
            // further.
            final float totalReqPixelsCap = reqWidth * reqHeight * 2;

            while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
                inSampleSize++;
            }
        }
        return inSampleSize;
    }

    public static int parserColor(String c) {
        int color = 0;
        try {
            color = Color.parseColor(c);
        } catch (IllegalArgumentException e) {
        } catch (Exception e) {
        }
        return color;
    }

    public static Bitmap drawableToBitmap(Drawable drawable) {
        // 取 drawable 的长宽
        int w = drawable.getIntrinsicWidth();
        int h = drawable.getIntrinsicHeight();

        // 取 drawable 的颜色格式
        Bitmap.Config config = (drawable.getOpacity() != PixelFormat.OPAQUE) ? Bitmap.Config.ARGB_8888
                : Bitmap.Config.RGB_565;
        // 建立对应 bitmap
        Bitmap bitmap = Bitmap.createBitmap(w, h, config);
        // 建立对应 bitmap 的画布
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, w, h);
        // 把 drawable 内容画到画布中
        drawable.draw(canvas);
        return bitmap;
    }

    public static void execCmds(String path) {
        File temp = new File(path);
        if (temp.exists()) {
            temp.delete();
        }
        Runtime runtime = Runtime.getRuntime();
        Process proc = null;
        try {
            proc = runtime.exec("screencap -p " + path);
        } catch (IOException e1) {
            Log.d(TAG, e1.getMessage());
        }
        // 这句话就是shell与高级语言间的调用
        // 如果有参数的话可以用另外一个被重载的exec方法
        // 实际上这样执行时启动了一个子进程,它没有父进程的控制台
        // 也就看不到输出,所以我们需要用输出流来得到shell执行后的输出
        InputStream inputstream = proc.getInputStream();
        InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
        BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
        String line = "";
        StringBuilder sb = new StringBuilder(line);
        try {
            while ((line = bufferedreader.readLine()) != null) {
                sb.append(line);
                sb.append('\n');
            }
        } catch (IOException e1) {
            Log.d(TAG, e1.getMessage());
        }

        // 使用exec执行不会等执行成功以后才返回,它会立即返回
        // 所以在某些情况下是很要命的(比如复制文件的时候)
        // 使用wairFor()可以等待命令执行完成以后才返回
        try {
            if (proc.waitFor() != 0) {
                Log.d(TAG, "exit value = " + proc.exitValue());
            }
        } catch (InterruptedException e) {
            Log.d(TAG, e.getMessage());
        }
    }
}
